package com.boarsoft.flow.exchange;

import java.io.File;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.ResourceEntityResolver;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.FileSystemResource;

import com.boarsoft.common.util.FileUtil;
import com.boarsoft.flow.core.SimpleFlow;
import com.boarsoft.flow.core.SimpleFlowEngine;
import com.boarsoft.flow.store.SimpleFlowStore;

public class SimpleFlowExchangerImpl implements FlowExchanger {
	private static final Logger log = LoggerFactory.getLogger(SimpleFlowExchangerImpl.class);

	/** */
	@Autowired
	protected DefaultListableBeanFactory beanFactory;
	/** */
	@Autowired
	protected ConfigurableApplicationContext applicationContext;
	/** */
	protected SimpleFlowStore flowStore;
	/** */
	protected SimpleFlowEngine flowEngine;

	@Override
	public SimpleFlow exchange(String path, String code, String content) {
		String fp = flowStore.getXmlFilePath(path, code);
		log.info("Recevied flow xml {}", fp);
		// 将XML写入文件
		try {
			File f = new File(fp);
			FileUtil.makePath(f.getParent());
			FileUtil.write(f, content);
		} catch (Exception e) {
			log.error("Error on write bean definition to xml {}", fp, e);
			return null;
		}
		// 关闭流程引擎（暂停服务）清除流程和对象缓存
		flowEngine.close();
		try {
			// 将XML转换为BEAN
			log.info("Load beans from {}", fp);
			XmlBeanDefinitionReader xbdr = new XmlBeanDefinitionReader(beanFactory);
			xbdr.setResourceLoader(applicationContext);
			xbdr.setEntityResolver(new ResourceEntityResolver(applicationContext));
			try {
				xbdr.loadBeanDefinitions(new FileSystemResource(fp));
			} catch (Exception e) {
				log.error("Error on load bean definitions from {}", fp, e);
				return null;
			}
			if (applicationContext.containsBean(code)) {
				log.info("Load bean {} from {} sucessfully", code, fp);
				return (SimpleFlow) applicationContext.getBean(code);
			}
			log.error("Load beans from {} failed", fp);
		} finally {
			flowEngine.open();
		}
		return null;
	}

	public SimpleFlowStore getFlowStore() {
		return flowStore;
	}

	public void setFlowStore(SimpleFlowStore flowStore) {
		this.flowStore = flowStore;
	}

	public SimpleFlowEngine getFlowEngine() {
		return flowEngine;
	}

	public void setFlowEngine(SimpleFlowEngine flowEngine) {
		this.flowEngine = flowEngine;
	}
}